﻿using System;
using System.Collections.Generic;
using System.Text;
using SharpSvn;
using System.Collections.ObjectModel;

namespace TSVNAddin.SVN
{
	public class SVNClientAdapter : IVersionControl
	{
		private readonly Dictionary<SvnStatus, VersionControlStatus> statusMap = new Dictionary<SvnStatus, VersionControlStatus>
			{
				{ SvnStatus.None, VersionControlStatus.None },
				{ SvnStatus.NotVersioned, VersionControlStatus.Unversioned },
				{ SvnStatus.Normal, VersionControlStatus.Normal },
				{ SvnStatus.Added, VersionControlStatus.Added },
				{ SvnStatus.Deleted, VersionControlStatus.Deleted },
				{ SvnStatus.Modified, VersionControlStatus.Modified },
				{ SvnStatus.Conflicted, VersionControlStatus.Conflicted },
				{ SvnStatus.Ignored, VersionControlStatus.Ignored }
				//{ VersionControlStatus.Locked, SvnStatus. },
				//{ VersionControlStatus.ReadOnly, SvnStatus. },
			};

        public virtual bool Contains(string path)
        {
            return GetInfo(path) != null;
        }

		private SVNInfoArgs GetInfo(string path)
		{
			using (SvnClient client = new SvnClient())
			{
				SvnInfoEventArgs info;
				SvnTarget svnTarget = SvnTarget.FromString(path);

				try
				{
					client.GetInfo(svnTarget, out info);
				}
				catch (SvnException ex)
				{
					return null;
				}

				return new SVNInfoArgs()
				{
					RepositoryRoot = info.RepositoryRoot,
					Uri = info.Uri
				};
			}
		}

		public VersionControlStatus GetStatus(string path)
		{
			using (SvnClient client = new SvnClient())
			{
				try
				{
					//SvnStatusArgs sa = new SvnStatusArgs();
					//sa.Depth = SvnDepth.Empty; // Adjust this to check direct files, or (recursive) directories etc

					Collection<SvnStatusEventArgs> statuses;
					client.GetStatus(path, out statuses);

					if (statuses.Count == 0)
						return VersionControlStatus.Normal;

					SvnStatus status = statuses[0].LocalContentStatus;

					return ConvertStatus(status);
				}
				catch (SvnException ex)
				{
					return VersionControlStatus.None;
				}
			}
		}

		private VersionControlStatus ConvertStatus(SvnStatus status)
		{
			if (!statusMap.ContainsKey(status))
				return VersionControlStatus.None;

			return statusMap[status];
		}

		public void Add(string path)
		{
			using (SvnClient client = new SvnClient())
			{
				var args = new SvnAddArgs()
				{
					Force = true,
					AddParents = true,
					Depth = SvnDepth.Empty
				};
				client.Add(path, args);
			}
		}

		public void Delete(string path)
		{
			using (SvnClient client = new SvnClient())
			{
				client.Delete(path);
			}
		}

		public void Move(string sourcePath, string toPath)
		{
			using (SvnClient client = new SvnClient())
			{
				client.Move(sourcePath, toPath);
			}
		}

		public bool Relocate(string path, Uri from, Uri to)
		{
			using (SvnClient client = new SvnClient())
			{
				try
				{
					//var args = new SvnMoveArgs()
					//{
					//    Force = true
					//};
					return client.Relocate(path, from, to);
				}
				catch (SvnException ex)
				{
					//Log
					return false;
				}
			}
		}

		public void AddToIgnoreList(string containerPath, string toIgnore)
		{
			using (SvnClient client = new SvnClient())
			{
				try
				{
					string ignoredValue;
					client.GetProperty(SvnTarget.FromString(containerPath), SvnPropertyNames.SvnIgnore, out ignoredValue);

					if (ignoredValue != string.Empty)
						ignoredValue += "\r\n";

					string newIgnoredValue = ignoredValue + toIgnore;
					client.SetProperty(containerPath, SvnPropertyNames.SvnIgnore, newIgnoredValue);
				}
				catch (SvnException ex)
				{
					//Log
				}
			}
		}
	}
}
